home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 43
/
Aminet 43 (2001)(GTI - Schatztruhe)[!][Jun 2001].iso
/
Aminet
/
game
/
think
/
Connect4.lha
/
Connect4
/
source
/
graphics_support.c
< prev
next >
Wrap
C/C++ Source or Header
|
2001-03-28
|
14KB
|
404 lines
#include "graphics_support.h"
#include <clib/graphics_protos.h>
#include <libraries/iffparse.h>
#include <datatypes/pictureclass.h>
#include <clib/iffparse_protos.h>
#include <stdio.h>
/*
** INPUTS:
** bitmap = pointer to a bitmap (the bitmap contents will be altered)
** cm = pointer to ColorMap of the viewport
** palette = pointer to an array of RGB values the bitmap would like to use
** pens = pointer to an array of storage for (hopefully) allocated pens
** NB: all elements of pens array must be set to 0, prior to calling this function!
** num_pens = the size of the array (how many pens it can hold)
**
** RESULT:
** None
**
** NOTES:
** This call must be matched with a call to freeallocatedpens()
*/
void remapbitmap (struct BitMap *bitmap, struct ColorMap *cm, ULONG *palette, struct pen *pens, UWORD num_pens)
{
ULONG R, G, B;
UBYTE cmap_index[8]; // each pixel ends up with its cmap index val in cmap[pixel]
WORD i;
UWORD row, byteinrow;
ULONG offset=0;
for (row=0; row<bitmap->Rows; row++)
{
for (byteinrow=0; byteinrow<bitmap->BytesPerRow; byteinrow++)
{
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("offset:%d\n", offset);
#endif
// Read in 8 pixels down through the relevant bitplanes
{
int plane_shift;
int buffer[8];
// Erase contents of cmap_index and buffer
for (i=0; i<8; i++)
{
cmap_index[i]=0;
buffer[i]=0;
}
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("Reading plane data\n");
#endif
// Plane[0] is least significant plane!
plane_shift=bitmap->Depth-1;
for (i=bitmap->Depth-1; i>=0; i--)
{
buffer[i]=*(bitmap->Planes[i]+offset);
cmap_index[0]=((UBYTE)(((buffer[i] & 128) >> 7) << plane_shift)) | cmap_index[0];
cmap_index[1]=((UBYTE)(((buffer[i] & 64) >> 6) << plane_shift)) | cmap_index[1];
cmap_index[2]=((UBYTE)(((buffer[i] & 32) >> 5) << plane_shift)) | cmap_index[2];
cmap_index[3]=((UBYTE)(((buffer[i] & 16) >> 4) << plane_shift)) | cmap_index[3];
cmap_index[4]=((UBYTE)(((buffer[i] & 8) >> 3) << plane_shift)) | cmap_index[4];
cmap_index[5]=((UBYTE)(((buffer[i] & 4) >> 2) << plane_shift)) | cmap_index[5];
cmap_index[6]=((UBYTE)(((buffer[i] & 2) >> 1) << plane_shift)) | cmap_index[6];
cmap_index[7]=((UBYTE)(((buffer[i] & 1) ) << plane_shift)) | cmap_index[7];
plane_shift--;
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("buffer[%d]:%4.d cmap0:%d cmap1:%d cmap2:%d cmap3:%d cmap4:%d cmap5:%d cmap6:%d cmap7:%d\n",
i, buffer[i], cmap_index[0], cmap_index[1], cmap_index[2], cmap_index[3], cmap_index[4], cmap_index[5], cmap_index[6], cmap_index[7]);
#endif
}
}
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("\n");
#endif
// Allocate any pens we need
for (i=0; i<8; i++) // Test each pixel
{
if (cmap_index[i]!=0) // Ignore colour 0, which should be a transparent background
{
int index=3*cmap_index[i];
R=palette[index];
G=palette[index+1];
B=palette[index+2];
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("R=%x G=%x B=%x\n", R, G, B);
#endif
if (!alreadyallocated(R, G, B, pens, num_pens))
{
WORD freepen;
if ((freepen=findfreepen(pens, num_pens))!=-1)
{
if ((pens[freepen].number=ObtainBestPen(cm, R, G, B, OBP_Precision, PRECISION_IMAGE, TAG_DONE))!=-1)
{
pens[freepen].red=R;
pens[freepen].green=G;
pens[freepen].blue=B;
}
}
}
}
}
// Give every pixel that needs it its new pen value
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("Reassigning pixel pen values\n");
#endif
for (i=0; i<8; i++)
{
if (cmap_index[i]!=0) // Ignore colour 0, which should be a transparent background
{
WORD gotpen;
R=palette[3*cmap_index[i]];
G=palette[3*cmap_index[i]+1];
B=palette[3*cmap_index[i]+2];
if ((gotpen=findallocatedpen(R, G, B, pens, num_pens))!=-1)
{
cmap_index[i]=(UBYTE)(pens[gotpen].number);
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("gotpen:%4.d pennum=%4.d cmap[%d]:%d\n", gotpen, pens[gotpen].number, i, cmap_index[i]);
#endif
}
}
#ifdef GRAPHICS_SUPPORT_DEBUG
else
printf("Skipped colour 0\n");
#endif
}
#ifdef GRAPHICS_SUPPORT_DEBUG
print_pens(pens, num_pens);
printf("\n");
#endif
// Write 8 pixels back into bitmap with new cmap index values for current
// viewport's struct ColorMap
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("Writing plane data\n");
#endif
{
UBYTE buffer;
int bitmask=1;
int shift=0;
for (i=bitmap->Depth-1; i>0; i--)
bitmask=bitmask*2;
// Plane[0] is least significant plane!
for (i=bitmap->Depth-1; i>=0; i--)
{
buffer= ((cmap_index[0] & bitmask)<<shift)
| ((cmap_index[1] & bitmask)<<shift)>>1
| ((cmap_index[2] & bitmask)<<shift)>>2
| ((cmap_index[3] & bitmask)<<shift)>>3
| ((cmap_index[4] & bitmask)<<shift)>>4
| ((cmap_index[5] & bitmask)<<shift)>>5
| ((cmap_index[6] & bitmask)<<shift)>>6
| ((cmap_index[7] & bitmask)<<shift)>>7;
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("bitmask:%4.d i:%d buffer:%d\n", bitmask, i, buffer);
#endif
*(bitmap->Planes[i]+offset)=buffer;
bitmask=bitmask>>1;
shift++;
}
}
#ifdef GRAPHICS_SUPPORT_DEBUG
printf("\n\n");
#endif
offset++;
}
}
}
/*
** INPUTS:
** pens = pointer to an array of pen numbers
** num_pens = the size of the array (how many pens it can hold)
** NB: max = 256
**
** RESULT:
** The free pen index, or -1 on failure
*/
WORD findfreepen (struct pen *pens, UWORD num_pens)
{
UWORD i;
for (i=0; i<num_pens; i++)
{
if (pens[i].number==-1)
return i;
}
return -1; // if we get this far, there were no free pens
}
/*
** INPUTS:
** R, G, B = red, green and blue values (32 bit left justified fraction)
** pens = pointer to an array of pen numbers
** num_pens = the size of the array (how many pens it can hold)
** NB: max = 256
**
** RESULT:
** TRUE if we already have a suitable pen, FALSE otherwise
*/
BOOL alreadyallocated (ULONG R, ULONG G, ULONG B, struct pen *pens, UWORD num_pens)
{
UWORD i;
for (i=0; i<num_pens; i++)
{
if (pens[i].red==R && pens[i].green==G && pens[i].blue==B)
return TRUE;
}
return FALSE;
}
/*
** INPUTS:
** R, G, B = red, green and blue values (32 bit left justified fraction)
** pens = pointer to an array of pen numbers
** num_pens = the size of the array (how many pens it can hold)
** NB: max = 256
**
** RESULT:
** An index into our array of allocated pens, or -1 if no matching pen is found
*/
WORD findallocatedpen (ULONG R, ULONG G, ULONG B, struct pen *pens, UWORD num_pens)
{
UWORD i;
for (i=0; i<num_pens; i++)
{
if (pens[i].red==R && pens[i].green==G && pens[i].blue==B && pens[i].number!=-1)
return i;
}
return -1;
}
/*
** INPUTS:
** cm = pointer to ColorMap of the viewport
** pens = pointer to an array of pen numbers
** num_pens = the size of the array (how many pens it can hold)
** NB: max = 256
**
** RESULT:
** None
*/
void freeallocatedpens (struct ColorMap *cm, struct pen *pens, UWORD num_pens)
{
UWORD i;
for (i=0; i<num_pens; i++)
{
if (pens[i].number!=-1)
ReleasePen(cm, pens[i].number);
else
break;
}
}
#ifdef GRAPHICS_SUPPORT_DEBUG
void print_pens (struct pen *pens, UWORD num_pens)
{
UWORD i;
printf("Pens: ");
for (i=0; i<num_pens; i++)
{
if (pens[i].number!=-1)
printf("%3.d = R:%x G:%x B%x\n", pens[i].number, pens[i].red, pens[i].green, pens[i].blue);
else
break;
}
printf("\n");
}
#endif
struct BitMap *bodytobitmap (ULONG width, ULONG height, ULONG depth, UBYTE *body)
{
struct BitMap *bitmap;
// Allocate 8 bitplanes so that the remapping routine has room to write
// back pen numbers from ObtainBestPen() with values up to 255
bitmap=AllocBitMap(width, height, 8, BMF_CLEAR | BMF_MINPLANES, NULL);
{
char plane, scanline;
int row_width=((width+15)/16)*2; // row width in bytes
UBYTE *body_rover;
int plane_offset=0;
body_rover=body;
for (scanline=0; scanline<height; scanline++)
{
for (plane=0; plane<depth; plane++)
{
memcpy(bitmap->Planes[plane]+plane_offset, body_rover, row_width);
body_rover+=row_width;
}
plane_offset=row_width*(scanline+1);
}
}
return bitmap;
}
BOOL loadiff (char *filename, ULONG *width, ULONG *height, ULONG *depth, ULONG *compression, UBYTE **body, ULONG **palette)
{
struct IFFHandle *iff;
BOOL result=FALSE;
if (iff=AllocIFF())
{
if (iff->iff_Stream=Open(filename, MODE_OLDFILE))
{
InitIFFasDOS(iff);
if (!OpenIFF(iff, IFFF_READ))
{
if (!PropChunk(iff, ID_ILBM, ID_BMHD))
{
if (!PropChunk(iff, ID_ILBM, ID_CMAP))
{
if (!StopChunk(iff, ID_ILBM, ID_BODY))
{
ParseIFF(iff, IFFPARSE_SCAN);
{
struct StoredProperty *bmhd;
if (bmhd=FindProp(iff, ID_ILBM, ID_BMHD))
{
struct BitMapHeader *the_bmhd;
the_bmhd=(struct BitMapHeader *)bmhd->sp_Data;
*width=the_bmhd->bmh_Width;
*height=the_bmhd->bmh_Height;
*depth=the_bmhd->bmh_Depth;
// Don't store bmh_Compression value if compression==NULL
if (compression)
*compression=the_bmhd->bmh_Compression;
}
}
{
struct StoredProperty *cmap;
if (cmap=FindProp(iff, ID_ILBM, ID_CMAP))
{
int num_primary_colours=cmap->sp_Size;
UBYTE *primary_colour=cmap->sp_Data;
int i;
*palette=(ULONG *)calloc(num_primary_colours, sizeof(ULONG));
memset(*palette, 0, sizeof(ULONG)*num_primary_colours);
for (i=0; i<num_primary_colours; i++)
{
(*palette)[i]=*primary_colour++;
(*palette)[i]=(*palette)[i]<<24;
}
}
}
{
struct ContextNode *cn;
cn=CurrentChunk(iff);
*body=(UBYTE *)malloc(cn->cn_Size);
ReadChunkBytes(iff, *body, cn->cn_Size);
}
result=TRUE;
}
}
}
CloseIFF(iff);
}
Close(iff->iff_Stream);
}
FreeIFF(iff);
}
return result;
}